{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Deep Reinfocement Learning - Evolution Strategies - Chapter 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import random\n",
    "from matplotlib import pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "alphabet = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,.! \"\n",
    "target = \"Hello World!\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Individual:\n",
    "    def __init__(self, string, fitness=0):\n",
    "        self.string = string\n",
    "        self.fitness = fitness"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "from difflib import SequenceMatcher\n",
    "\n",
    "def similar(a, b):\n",
    "    return SequenceMatcher(None, a, b).ratio()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def spawn_population(length=26,size=100):\n",
    "    pop = []\n",
    "    for i in range(size):\n",
    "        string = ''.join(random.choices(alphabet,k=length))\n",
    "        individual = Individual(string)\n",
    "        pop.append(individual)\n",
    "    return pop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def mutate(x, mut_rate=0.01):\n",
    "    new_x_ = []\n",
    "    for char in x.string:\n",
    "        if random.random() < mut_rate:\n",
    "            new_x_.extend(random.choices(alphabet,k=1))\n",
    "        else:\n",
    "            new_x_.append(char)\n",
    "    new_x = Individual(''.join(new_x_))\n",
    "    return new_x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "def recombine(p1_, p2_): #produces two children from two parents\n",
    "    p1 = p1_.string\n",
    "    p2 = p2_.string\n",
    "    child1 = []\n",
    "    child2 = []\n",
    "    cross_pt = random.randint(0,len(p1))\n",
    "    child1.extend(p1[0:cross_pt])\n",
    "    child1.extend(p2[cross_pt:])\n",
    "    child2.extend(p2[0:cross_pt])\n",
    "    child2.extend(p1[cross_pt:])\n",
    "    c1 = Individual(''.join(child1))\n",
    "    c2 = Individual(''.join(child2))\n",
    "    return c1, c2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def evaluate_population(pop, target):\n",
    "    avg_fit = 0\n",
    "    for i in range(len(pop)):\n",
    "        fit = similar(pop[i].string, target)\n",
    "        pop[i].fitness = fit\n",
    "        avg_fit += fit\n",
    "    avg_fit /= len(pop)\n",
    "    return pop, avg_fit"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [],
   "source": [
    "def next_generation(pop, size=100, length=26, mut_rate=0.01):\n",
    "    new_pop = []\n",
    "    while len(new_pop) < size:\n",
    "        parents = random.choices(pop,k=2, weights=[x.fitness for x in pop])\n",
    "        offspring_ = recombine(parents[0],parents[1])\n",
    "        offspring = [mutate(offspring_[0], mut_rate=mut_rate), mutate(offspring_[1], mut_rate=mut_rate)]\n",
    "        new_pop.extend(offspring) #add offspring to next generation\n",
    "    return new_pop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "pop = spawn_population(length=len(target))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.115\n"
     ]
    }
   ],
   "source": [
    "pop, avg_fit = evaluate_population(pop, target)\n",
    "print(avg_fit)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "new_pop = next_generation(pop, length=len(target))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.08333333333333333"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "new_pop[10].fitness"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [],
   "source": [
    "num_generations = 100\n",
    "population_size = 3000\n",
    "str_len = len(target)\n",
    "mutation_rate = 0.001 # 0.1% mutation rate per character"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [],
   "source": [
    "pop_fit = []\n",
    "pop = spawn_population(size=population_size, length=str_len) #initial population\n",
    "for gen in range(num_generations):\n",
    "    # trainning\n",
    "    pop, avg_fit = evaluate_population(pop, target)\n",
    "    pop_fit.append(avg_fit) #record population average fitness\n",
    "    new_pop = next_generation(pop, size=population_size, length=str_len, mut_rate=mutation_rate)\n",
    "    pop = new_pop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 720x360 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(10,5))\n",
    "plt.xlabel(\"Generations\")\n",
    "plt.ylabel(\"Fitness\")\n",
    "plt.plot(pop_fit)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [],
   "source": [
    "pop.sort(key=lambda x: x.fitness, reverse=True) #sort in place, highest fitness first"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Hello Woldd!'"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pop[0].string"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [conda env:deeprl]",
   "language": "python",
   "name": "conda-env-deeprl-py"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
